package com.qqt.csr.archive.service;

import cn.hutool.core.util.StrUtil;
import com.qqt.csr.archive.assembler.MessageArchiveAssembler;
import com.qqt.csr.archive.entity.reader.CsrImAccount;
import com.qqt.csr.archive.entity.reader.CsrSkillSetConfig;
import com.qqt.csr.archive.entity.reader.ImH5Manage;
import com.qqt.csr.archive.entity.reader.SysUser;
import com.qqt.csr.archive.entity.writer.ArchiveConversation;
import com.qqt.csr.archive.entity.writer.ArchiveMessage;
import com.qqt.csr.archive.entity.writer.content.TextElemContent;
import com.qqt.csr.archive.enums.*;
import com.qqt.csr.archive.mapper.ArchiveMessageMapper;
import com.qqt.csr.archive.response.ArchiveMessageResponse;
import com.qqt.csr.common.sensitiveword.SensitiveWordReplaceHandler;
import com.qqt.csr.common.utils.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: yang hao
 * @Date: 2024/11/21 13:43
 * @Description: 归档消息 服务
 **/
@Slf4j
@Service
public class ArchiveMessageService {

    @Autowired
    private ArchiveMessageMapper archiveMessageMapper;
    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private CsrSkillSetConfigService csrSkillSetConfigService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private ImH5ManageService imH5ManageService;
    @Autowired
    private CsrImAccountService csrImAccountService;
    @Autowired
    private SensitiveWordReplaceHandler sensitiveWordReplaceHandler;

    /**
     * 根据消息id查询消息列表
     *
     * @param msgId {@link String} 消息id
     * @return {@link List<ArchiveMessage>} 归档消息列表
     */
    public List<ArchiveMessage> findByMsgId(String msgId) {
        Criteria criteria = Criteria.where("id").is(msgId);
        return mongoTemplate.find(Query.query(criteria), ArchiveMessage.class);
    }

    /**
     * 根据会话id查询消息列表
     *
     * @param conversationId {@link String} 会话id
     * @param conversation   {@link ArchiveConversation} 归档会话
     * @param userId         {@link String} 接收方id
     * @param source         {@link RequestSource} 请求方
     * @return {@link List<ArchiveMessageResponse>} 归档消息列表
     */
    public List<ArchiveMessageResponse> findByConversationIdAndUserId(String conversationId, ArchiveConversation conversation, String userId, RequestSource source) {
        Criteria criteria = Criteria.where("conversationId").is(conversationId);
        if (!RequestSource.WEB.equals(source)) {
            // 客服工作台及访客端历史记录查询
            criteria.and("recipient.accountUserId").is(userId);
        }
        Query query = Query.query(criteria).with(Sort.by(Sort.Order.asc("seq")));
        List<ArchiveMessage> messages = mongoTemplate.find(query, ArchiveMessage.class);
        if (RequestSource.WEB.equals(source)) {
            // 后台管理的会话记录查询的，需要把带敏感词被拦截但未在客服端显示的消息一并查询，并且站在客服视角，发送方是客服的需要把flow为IN改为OUT
            Map<String, ArchiveMessage> msgMap = new HashMap<>();
            for (ArchiveMessage msg : messages) {
                if (msgMap.containsKey(msg.getSeq())) {
                    continue;
                }

                if (msg.getSender() != null && msg.getSender().getAccountUserId().equals(userId)) {
                    msg.setFlow(FlowType.OUT);
                } else if (msg.getSender() != null) {
                    msg.setFlow(FlowType.IN);
                }
                msgMap.put(msg.getSeq(), msg);
            }
            messages = msgMap.values().stream().sorted(Comparator.comparing(ArchiveMessage::getSeq)).collect(Collectors.toList());
        }

        // 敏感词处理
        for (ArchiveMessage message : messages) {
            if (CollectionUtils.isNotEmpty(message.getSensitiveWords()) && MessageType.TextElem.equals(message.getType())) {
                TextElemContent swTextContent = JsonUtil.toObject(JsonUtil.toJson(message.getContent()), TextElemContent.class);
                if (RequestSource.WEB.equals(source)) {
                    // 会话记录查询的，直接默认是高亮
                    message.getSensitiveWords().forEach(sw -> sw.setShowType(1));
                }
                Optional.ofNullable(swTextContent).ifPresent(content -> {
                    swTextContent.setText(sensitiveWordReplaceHandler.replace(swTextContent.getText(), message.getSensitiveWords()));
                    message.setContent(swTextContent);
                });
            }
        }
        List<ArchiveMessageResponse> responses = MessageArchiveAssembler.convert(messages);
        // 填充客服头像
        return switch (source) {
            case WEB, WORKBENCH -> {
                responses = fillWebHeadImg(conversation, responses);
                yield fillVisitorWebHeadImg(conversation, responses);
            }
            case H5 -> fillHeadImg(conversation, responses);
        };
    }

    /**
     * 保存
     *
     * @param archiveMessages {@link List<ArchiveMessage>} 归档消息集
     */
    public void save(List<ArchiveMessage> archiveMessages) {
        archiveMessageMapper.saveAll(archiveMessages);
    }

    /**
     * 填充客服头像 根据配置
     *
     * @param conversation {@link ArchiveConversation} 归档会话
     * @param responses    {@link List<ArchiveMessageResponse>} 归档消息列表
     * @return {@link List<ArchiveMessageResponse>} 归档消息列表
     */
    public List<ArchiveMessageResponse> fillHeadImg(ArchiveConversation conversation, List<ArchiveMessageResponse> responses) {
        if (StrUtil.isBlank(conversation.getCsId())) {
            return responses;
        }
        // 12.12 需求调整，根据配置获取头像/昵称
        String headImgUrl = null;
        String nickname = null;
        ConversationType type = ConversationType.matchIgnoreCase(conversation.getConversationType());
        // 人工客服
        if (ConversationType.ARTIFICIAL.equals(type)) {
            // 获取配置
            ImH5Manage imH5Manage = imH5ManageService.getById(conversation.getChannelId());
            if (imH5Manage == null) {
                return responses;
            }
            // 技能组形象
            if (1 == imH5Manage.getAppearanceType()) {
                CsrSkillSetConfig skillSetConfig = csrSkillSetConfigService.getBySkillSetId(Long.parseLong(conversation.getSkillSetId()));
                headImgUrl = skillSetConfig == null ? null : skillSetConfig.getCsHeadImg();
                nickname = skillSetConfig == null ? null : skillSetConfig.getCsNickname();
            }
            // 客服头像
            if (0 == imH5Manage.getAppearanceType()) {
                SysUser sysUser = sysUserService.getById(conversation.getCsId());
                headImgUrl = sysUser == null ? null : sysUser.getAvatar();
                nickname = sysUser == null ? null : sysUser.getNickName();
            }
        }
        // 填充
        String finalHeadImgUrl = headImgUrl;
        String finalNickname = nickname;
        responses.forEach(response -> {
            if (response.getSender() != null && AccountType.CUSTOMER_SERVICE.equals(response.getSender().getType())) {
                response.getSender().setHeadImg(finalHeadImgUrl);
                response.getSender().setAccountName(finalNickname);
            }
            if (response.getRecipient() != null && AccountType.CUSTOMER_SERVICE.equals(response.getRecipient().getType())) {
                response.getRecipient().setHeadImg(finalHeadImgUrl);
                response.getRecipient().setAccountName(finalNickname);
            }
        });
        return responses;
    }

    /**
     * 填充客服头像 默认为客服自身头像 12.18 需求逻辑调整
     *
     * @param conversation {@link ArchiveConversation} 归档会话
     * @param responses    {@link List<ArchiveMessageResponse>} 归档消息列表
     * @return {@link List<ArchiveMessageResponse>} 归档消息列表
     */
    public List<ArchiveMessageResponse> fillWebHeadImg(ArchiveConversation conversation, List<ArchiveMessageResponse> responses) {
        if (StrUtil.isBlank(conversation.getCsId())) {
            return responses;
        }
        String headImgUrl = null;
        String nickname = null;
        ConversationType type = ConversationType.matchIgnoreCase(conversation.getConversationType());
        // 人工客服
        if (ConversationType.ARTIFICIAL.equals(type)) {
            SysUser sysUser = sysUserService.getById(conversation.getCsId());
            headImgUrl = sysUser == null ? null : sysUser.getAvatar();
            nickname = sysUser == null ? null : sysUser.getNickName();
        }
        // 填充
        String finalHeadImgUrl = headImgUrl;
        String finalNickname = nickname;
        responses.forEach(response -> {
            if (response.getSender() != null && AccountType.CUSTOMER_SERVICE.equals(response.getSender().getType())) {
                response.getSender().setHeadImg(finalHeadImgUrl);
                response.getSender().setAccountName(finalNickname);
            }
            if (response.getRecipient() != null && AccountType.CUSTOMER_SERVICE.equals(response.getRecipient().getType())) {
                response.getRecipient().setHeadImg(finalHeadImgUrl);
                response.getRecipient().setAccountName(finalNickname);
            }
        });
        return responses;
    }

    /**
     * 填充访客头像 默认为客服自身头像 12.18 需求逻辑调整
     *
     * @param conversation {@link ArchiveConversation} 归档会话
     * @param responses    {@link List<ArchiveMessageResponse>} 归档消息列表
     * @return {@link List<ArchiveMessageResponse>} 归档消息列表
     */
    public List<ArchiveMessageResponse> fillVisitorWebHeadImg(ArchiveConversation conversation, List<ArchiveMessageResponse> responses) {
        if (StrUtil.isBlank(conversation.getUserAccountId())) {
            return responses;
        }
        String headImgUrl = null;
        String nickname = null;
        ConversationType type = ConversationType.matchIgnoreCase(conversation.getConversationType());
        // 人工客服
        if (ConversationType.ARTIFICIAL.equals(type)) {
            CsrImAccount account = csrImAccountService.getById(conversation.getUserAccountId());
            headImgUrl = account == null ? null : account.getHeadImg();
            nickname = account == null ? null : account.getAccountName();
        }
        // 填充
        String finalHeadImgUrl = headImgUrl;
        String finalNickname = nickname;
        responses.forEach(response -> {
            if (response.getSender() != null && AccountType.VISITOR.equals(response.getSender().getType())) {
                response.getSender().setHeadImg(finalHeadImgUrl);
                response.getSender().setAccountName(finalNickname);
            }
            if (response.getRecipient() != null && AccountType.VISITOR.equals(response.getRecipient().getType())) {
                response.getRecipient().setHeadImg(finalHeadImgUrl);
                response.getRecipient().setAccountName(finalNickname);
            }
        });
        return responses;
    }

}
